﻿using IDEAMS.core;
using IDEAMS.core.deviceClient;
using IDEAMS.core.opm;
using IDEAMS.core.queue;
using IDEAMS.model;
using IDEAMS.model.alarm;
using IDEAMS.model.etalon;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Threading;
using System.Windows;


namespace IDEAMS.view.detection
{
    /// <summary>
    /// EtalonTextDlg.xaml 的交互逻辑
    /// </summary>
    public partial class EtalonTextDlg : Window
    {
        public EtalonTextDlgViewModel windowViewModel;
        private DeviceClient client;

        /// <summary>
        /// 波长接收线程
        /// </summary>
        OPM_MsgWorker peaksRefreshMsgWorker = null;
        private readonly object peaksLocker = new object(); //peaks 发现的locker

        public EtalonTextDlg()
        {
            InitializeComponent();

            windowViewModel = new EtalonTextDlgViewModel();
            this.DataContext = windowViewModel;

            this.Closing += new System.ComponentModel.CancelEventHandler(Window_Closing);

            this.btnStart.Click += new RoutedEventHandler(Start_Click);
            this.btnEnd.Click += new RoutedEventHandler(End_Click);

            this.btnPass.Click += new RoutedEventHandler(Pass_Click);
            this.btnFail.Click += new RoutedEventHandler(Fail_Click);
            this.btnCancel.Click += new RoutedEventHandler(Cancel_Click);
        }

        private void Window_Closing(object sender, CancelEventArgs e)
        {
            //client.dataWorker.OPMStop();
            Thread th = new Thread(new ThreadStart(StopPeaksRefreshWorker));
            th.Start();
        }

        public EtalonTextDlg(DeviceInfoViewModel deviceInfo) : this()
        {
            windowViewModel.deviceInfo = deviceInfo.Clone();
            windowViewModel.printStatus.Load(deviceInfo.serialNo);
            switch(deviceInfo.step)
            {
                case ProcessStep.PRE_ETALON:
                    windowViewModel.title = "标准具检测（烤机前）";
                    this.cbIsPrint.IsChecked = windowViewModel.printStatus.preEtalon;
                    break;
                case ProcessStep.POST_ETALON:
                    windowViewModel.title = "标准具检测（烤机后）";
                    this.cbIsPrint.IsChecked = windowViewModel.printStatus.postEtalon;
                    break;
                default:
                    break;
            }

            client = TW_App.deviceClientManager.Find(deviceInfo.serialNo);

            peaksRefreshMsgWorker = CreatePeaksRefreshWorker();
        }

        private OPM_MsgWorker CreatePeaksRefreshWorker()
        {
            OPM_MsgWorker worker = new OPM_MsgWorker();
            worker.handleProc = PeaksDataRefreshProc;
            worker.keyList.Add(QueueDataType.DATA_WL);

            return worker;
        }

        private void StartPeaksRefreshWorker()
        {
            if (peaksRefreshMsgWorker.IsStop())
            {
                if (client != null)
                {
                    client.Register(peaksRefreshMsgWorker, QueueDataType.DATA_WL);
                }
                peaksRefreshMsgWorker.StartAsync();
            }
        }

        private void StopPeaksRefreshWorker()
        {
            if (!peaksRefreshMsgWorker.IsStop())
            {
                peaksRefreshMsgWorker.Stop();
                if (client != null)
                {
                    client.UnRegister(peaksRefreshMsgWorker, QueueDataType.DATA_WL);
                }
            }
        }

        private bool isReadly = false;
        private int index = -1;
        private int channelNo = 0;
        private Dictionary<string, double> preValues = new Dictionary<string, double>();
        private ObservableCollection<CompareViewModel> values = new ObservableCollection<CompareViewModel>();
        DateTime sTime = DateTime.Now;
        private void PeaksDataRefreshProc(QueueData msg)
        {
            //发现peaks锁
            lock (peaksLocker)
            {
                Wave waveLenData = (Wave)msg;

                if (!isReadly)
                {
                    //App.Current.Dispatcher.Invoke((Action)(() =>
                    //{
                    //    windowViewModel.values.Clear();
                    //}));
                    values.Clear();
                    foreach (var item in waveLenData.chGratting)
                    {
                        if (item.ngrating == 0) continue;
                        for (int i = 0; i < item.waveValueArray.Length; i++)
                        {
                            if (index < 0 && i == 0)
                            {
                                for(int j = 0; j< windowViewModel.selectedEtalon.values.Count-1; j++)
                                {
                                    if(windowViewModel.selectedEtalon.values[j] < item.waveValueArray[0] && windowViewModel.selectedEtalon.values[j+1] > item.waveValueArray[0])
                                    {
                                        index = (windowViewModel.selectedEtalon.values[j + 1] - item.waveValueArray[0]) > (item.waveValueArray[0] - windowViewModel.selectedEtalon.values[j]) ? j : j + 1;
                                        break;
                                    }
                                }
                                if(index < 0)
                                {
                                    return;
                                }
                                channelNo = item.chID+1;
                            }
                            CompareViewModel compareViewModel = new CompareViewModel();
                            compareViewModel.channelNo = item.chID+1;
                            compareViewModel.gratingNo = i + 1;
                            compareViewModel.name = "C" + compareViewModel.channelNo + "_S" + compareViewModel.gratingNo;
                            compareViewModel.srcValue = windowViewModel.selectedEtalon.values[index + i];
                            compareViewModel.dstValue = item.waveValueArray[i];
                            compareViewModel.diffValue = windowViewModel.selectedEtalon.values[index + i] - item.waveValueArray[i];
                            preValues.Add(compareViewModel.channelNo + "_" + compareViewModel.gratingNo, compareViewModel.dstValue);
                            //App.Current.Dispatcher.Invoke((Action)(() =>
                            //{
                            //    windowViewModel.values.Add(compareViewModel);
                            //}));
                            values.Add(compareViewModel);
                        }
                        break;
                    }
                    isReadly = true;
                }

                if(values.Count != waveLenData.chGratting[channelNo-1].waveValueArray.Length)
                {
                    AlarmInfo alarmInfo = new AlarmInfo();
                    alarmInfo.serialNo = windowViewModel.deviceInfo.serialNo;
                    alarmInfo.type = AlarmType.GRATING_COUNT_CHANGE;
                    alarmInfo.key = channelNo + "_" + ProcessStep.PRE_ETALON + "_" + AlarmType.GRATING_COUNT_CHANGE;
                    alarmInfo.channelNo = channelNo;
                    alarmInfo.gratingNo = 0;
                    alarmInfo.step = ProcessStep.PRE_ETALON;
                    alarmInfo.maxDiff = values.Count- waveLenData.chGratting[channelNo - 1].waveValueArray.Length;
                    alarmInfo.startTime = DateTime.Now;
                    alarmInfo.endTime = DateTime.Now;
                    alarmInfo.description = string.Format("光栅数由[{0}]个变成[{1}]个",values.Count, waveLenData.chGratting[channelNo - 1].waveValueArray.Length);
                    TW_App.delegateCollection.SyncAlarm(alarmInfo);
                    return;
                }
                for (int i = 0; i < values.Count; i++)
                {
                    values[i].dstValue = waveLenData.chGratting[channelNo - 1].waveValueArray[i];
                    values[i].diffValue = values[i].srcValue - values[i].dstValue;

                    if (Math.Abs(values[i].diffValue) > TW_App.globalSetting.threshold.fullThreshold)
                    {
                        AlarmInfo alarmInfo = new AlarmInfo();
                        alarmInfo.serialNo = windowViewModel.deviceInfo.serialNo;
                        alarmInfo.type = AlarmType.FULL;
                        alarmInfo.key = values[i].channelNo + "_" + values[i].gratingNo + "_" + ProcessStep.PRE_ETALON + "_" + AlarmType.FULL;
                        alarmInfo.channelNo = values[i].channelNo;
                        alarmInfo.gratingNo = values[i].gratingNo;
                        alarmInfo.step = ProcessStep.PRE_ETALON;
                        alarmInfo.maxDiff = values[i].diffValue;
                        alarmInfo.startTime = DateTime.Now;
                        alarmInfo.endTime = DateTime.Now;
                        TW_App.delegateCollection.SyncAlarm(alarmInfo);
                    }
                    if (Math.Abs(values[i].dstValue - preValues[values[i].channelNo+"_"+values[i].gratingNo]) > TW_App.globalSetting.threshold.adjoinThreshold)
                    {
                        AlarmInfo alarmInfo = new AlarmInfo();
                        alarmInfo.serialNo = windowViewModel.deviceInfo.serialNo;
                        alarmInfo.type = AlarmType.ADJION;
                        alarmInfo.key = values[i].channelNo + "_" + values[i].gratingNo + "_" + ProcessStep.PRE_ETALON + "_" + AlarmType.ADJION;
                        alarmInfo.channelNo = values[i].channelNo;
                        alarmInfo.gratingNo = values[i].gratingNo;
                        alarmInfo.step = ProcessStep.PRE_ETALON;
                        //alarmInfo.maxFullDiff = windowViewModel.values[i].diffValue;
                        alarmInfo.maxDiff = values[i].dstValue - preValues[values[i].channelNo + "_" + values[i].gratingNo];
                        alarmInfo.startTime = DateTime.Now;
                        alarmInfo.endTime = DateTime.Now;
                        TW_App.delegateCollection.SyncAlarm(alarmInfo);
                    }
                }

                if ((DateTime.Now - sTime).TotalMilliseconds > 500)
                {
                    App.Current.Dispatcher.Invoke((Action)(() =>
                    {
                        windowViewModel.values = values;
                    }));
                    sTime = DateTime.Now;
                }
            }
        }


        private void Start_Click(object sender, RoutedEventArgs e)
        {
            if(windowViewModel.selectedEtalon == null)
            {
                MessageBox.Show("请选择标准具","错误",MessageBoxButton.OK,MessageBoxImage.Error);
                return;
            }
            if (client != null && !client.dataWorker.isWaveStart)
            {
                client.dataWorker.OPMStart();
                client.dataWorker.isWaveStart = true;
            }

            StartPeaksRefreshWorker();
        }

        private void End_Click(object sender, RoutedEventArgs e)
        {
            if (client != null && client.dataWorker.isWaveStart)
            {
                client.dataWorker.isWaveStart = false;
                //client.dataWorker.OPMStop();
            }
            //StopPeaksRefreshWorker();
        }

        private void Pass_Click(object sender, RoutedEventArgs e)
        {
            DateTime dt = DateTime.Now;
            switch (windowViewModel.deviceInfo.step)
            {
                case ProcessStep.PRE_ETALON:
                    windowViewModel.deviceInfo.processResult.preEtalon = true;
                    windowViewModel.printStatus.preEtalon = this.cbIsPrint.IsChecked.Value;
                    break;
                case ProcessStep.POST_ETALON:
                    windowViewModel.deviceInfo.processResult.postEtalon = true;
                    windowViewModel.printStatus.postEtalon = this.cbIsPrint.IsChecked.Value;
                    break;
                default:
                    break;
            }

            windowViewModel.printStatus.Save(windowViewModel.deviceInfo.serialNo);

            if (client != null && client.dataWorker.isWaveStart)
            {
                //client.dataWorker.OPMStop();
                client.dataWorker.isWaveStart = false;
            }

            //发现peaks锁
            lock (peaksLocker)
            {
                CompareCollection compareCollection = new CompareCollection();
                foreach (var item in windowViewModel.values)
                {
                    compareCollection.Add(new Compare(item));
                }
                compareCollection.Save(windowViewModel.deviceInfo.serialNo, windowViewModel.deviceInfo.step);
            }

            // 查询当前检测步骤
            int index = TW_App.globalSetting.inspectionSequences.IndexOf((int)windowViewModel.deviceInfo.step);
            if(index == -1)
            {
                MessageBox.Show("当前处于未知检测项，请联系系统管理员","错误",MessageBoxButton.OK,MessageBoxImage.Error);
                return;
            }
            if(index == TW_App.globalSetting.inspectionSequences.Count-1)
            {
                windowViewModel.deviceInfo.step = ProcessStep.FINISHED;
            }
            else
            {
                windowViewModel.deviceInfo.step = (ProcessStep)TW_App.globalSetting.inspectionSequences[index + 1];
            }
            

            //if (client != null && client.dataWorker.isWaveStart)
            //{
            //    //client.dataWorker.OPMStop();
            //    client.dataWorker.isWaveStart = false;
            //}

            //Thread th = new Thread(new ThreadStart(StopPeaksRefreshWorker));
            //th.Start();
            //StopPeaksRefreshWorker();
            this.DialogResult = true;
        }

        private void Fail_Click(object sender, RoutedEventArgs e)
        {
            switch (windowViewModel.deviceInfo.step)
            {
                case ProcessStep.PRE_ETALON:
                    windowViewModel.deviceInfo.processResult.preEtalon = false;
                    break;
                case ProcessStep.POST_ETALON:
                    windowViewModel.deviceInfo.processResult.postEtalon = false;
                    break;
                default:
                    break;
            }

            if (client != null && client.dataWorker.isWaveStart)
            {
                client.dataWorker.isWaveStart = false;
                //client.dataWorker.OPMStop();
            }
            //StopPeaksRefreshWorker();

            this.DialogResult= true;
        }

        private void Cancel_Click(object sender, RoutedEventArgs e)
        {

            if (client != null && client.dataWorker.isWaveStart)
            {
                client.dataWorker.isWaveStart = false;
                //client.dataWorker.OPMStop();
            }
            //StopPeaksRefreshWorker();

            this.DialogResult = false;
        }
    }

    public class EtalonTextDlgViewModel : ViewModelBase
    {
        public PrintStatus printStatus;

        public EtalonTextDlgViewModel()
        {
            this.printStatus = new PrintStatus();

            values = new ObservableCollection<CompareViewModel>();

            etalons = new ObservableCollection<EtalonViewModel>();
            TW_App.etalonCollection.ForEach(x =>
            {
                etalons.Add(new EtalonViewModel(x));
                return false;
            });
            if(etalons.Count > 0)
            {
                selectedEtalon = etalons[0];
            }
        }

        private string m_title;
        public string title
        {
            get { return m_title; }
            set
            {
                m_title = value;
                NotifyPropertyChanged();
            }
        }

        private DeviceInfoViewModel m_deviceInfo;
        public DeviceInfoViewModel deviceInfo
        {
            get { return m_deviceInfo; }
            set
            {
                m_deviceInfo = value;
                NotifyPropertyChanged();
            }
        }

        private ObservableCollection<CompareViewModel> m_values;
        public ObservableCollection<CompareViewModel> values
        {
            get { return m_values; }
            set
            {
                m_values = value;
                NotifyPropertyChanged();
            }
        }

        private ObservableCollection<EtalonViewModel> m_etalons;
        public ObservableCollection<EtalonViewModel> etalons
        {
            get { return m_etalons; }
            set
            {
                m_etalons = value;
                NotifyPropertyChanged();
            }
        }

        private EtalonViewModel m_selectedEtalon;
        public EtalonViewModel selectedEtalon
        {
            get { return m_selectedEtalon; }
            set
            {
                m_selectedEtalon = value;
                NotifyPropertyChanged();
            }
        }
    }
}
